package mybatis;

import java.beans.Introspector;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 〈〉
 *
 * @author coach tam
 * @email 327395128@qq.com
 * @create 2023/10/17
 * @since 1.0.0
 * 〈坚持灵活 灵活坚持〉
 */
public class LambdaQueryWrapper<T> extends QueryWrapper<T> {

    protected ConcurrentHashMap<String, Object> params = new ConcurrentHashMap<>();

    public LambdaQueryWrapper() {
        this((T) null);
    }

    public LambdaQueryWrapper(T entity) {
        super.setEntityClass(entity);
    }

    @Override
    public String  whereSql() {
        /*Set<Map.Entry<String, Object>> entries = params.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            String key = entry.getKey();
            Object value = entry.getValue();
        }*/
/*        T entityClass = getEntityClass();
        TableName annotation = entityClass.getClass().getAnnotation(TableName.class);
        String tableName = annotation.value();*/

        return "where 1=1";
    }
    public LambdaQueryWrapper<T> eq(SerializableFunction<T,String> fun, String value) {
        String fieldName = getFieldName(fun);
        params.put(fieldName, value);
        return this;
    }

    private String getFieldName(SerializableFunction<T, String> function) {
        String fieldName = null;
        try {
            // 第1步 获取SerializedLambda
            //继承了Serializable接口，在实例化时会动态添加writeReplace方法实现
            Method method = function.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            //该方法会执行后会返回SerializedLambda对象
            SerializedLambda serializedLambda = (SerializedLambda) method.invoke(function);
            // 第2步 通过serializedLambda对象就能获取到方法引用对应的方法名
            String implMethodName = serializedLambda.getImplMethodName();

            //  第3步 转成标准的java字段命名
            // Thus "FooBah" becomes "fooBah" and "X" becomes "x", but "URL" stays as "URL".
            fieldName = Introspector.decapitalize(implMethodName.substring(3));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fieldName;
    }



}
